package com.koushikdutta.async.http;

import android.text.TextUtils;
import com.koushikdutta.async.AsyncServer;
import com.koushikdutta.async.AsyncSocket;
import com.koushikdutta.async.ByteBufferList;
import com.koushikdutta.async.DataEmitter;
import com.koushikdutta.async.DataSink;
import com.koushikdutta.async.FilteredDataEmitter;
import com.koushikdutta.async.LineEmitter;
import com.koushikdutta.async.LineEmitter.StringCallback;
import com.koushikdutta.async.NullDataCallback;
import com.koushikdutta.async.Util;
import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.WritableCallback;
import com.koushikdutta.async.http.body.AsyncHttpRequestBody;
import com.koushikdutta.async.http.filter.ChunkedOutputFilter;
import com.koushikdutta.async.http.libcore.RawHeaders;
import com.koushikdutta.async.http.libcore.ResponseHeaders;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;

abstract class AsyncHttpResponseImpl extends FilteredDataEmitter implements AsyncHttpResponse {
    static final /* synthetic */ boolean $assertionsDisabled = (!AsyncHttpResponseImpl.class.desiredAssertionStatus());
    boolean mCompleted = false;
    private boolean mFirstWrite = true;
    StringCallback mHeaderCallback = new StringCallback() {
        private RawHeaders mRawHeaders = new RawHeaders();

        public void onStringAvailable(String s) {
            try {
                s = s.trim();
                if (this.mRawHeaders.getStatusLine() == null) {
                    this.mRawHeaders.setStatusLine(s);
                } else if (TextUtils.isEmpty(s)) {
                    AsyncHttpResponseImpl.this.mHeaders = new ResponseHeaders(AsyncHttpResponseImpl.this.mRequest.getUri(), this.mRawHeaders);
                    AsyncHttpResponseImpl.this.onHeadersReceived();
                    if (AsyncHttpResponseImpl.this.mSocket != null) {
                        DataEmitter emitter;
                        if ("HEAD".equalsIgnoreCase(AsyncHttpResponseImpl.this.mRequest.getMethod())) {
                            emitter = EndEmitter.create(AsyncHttpResponseImpl.this.getServer(), null);
                        } else {
                            emitter = HttpUtil.getBodyDecoder(AsyncHttpResponseImpl.this.mSocket, this.mRawHeaders, false);
                        }
                        AsyncHttpResponseImpl.this.setDataEmitter(emitter);
                    }
                } else {
                    this.mRawHeaders.addLine(s);
                }
            } catch (Exception ex) {
                AsyncHttpResponseImpl.this.report(ex);
            }
        }
    };
    ResponseHeaders mHeaders;
    private CompletedCallback mReporter = new CompletedCallback() {
        public void onCompleted(Exception error) {
            if (error == null || AsyncHttpResponseImpl.this.mCompleted) {
                AsyncHttpResponseImpl.this.report(error);
            } else {
                AsyncHttpResponseImpl.this.report(new ConnectionClosedException("connection closed before response completed.", error));
            }
        }
    };
    private AsyncHttpRequest mRequest;
    DataSink mSink;
    private AsyncSocket mSocket;
    private AsyncHttpRequestBody mWriter;

    protected abstract void onHeadersReceived();

    public AsyncSocket getSocket() {
        return this.mSocket;
    }

    public AsyncHttpRequest getRequest() {
        return this.mRequest;
    }

    void setSocket(AsyncSocket exchange) {
        this.mSocket = exchange;
        if (this.mSocket != null) {
            this.mWriter = this.mRequest.getBody();
            if (this.mWriter != null) {
                if (this.mRequest.getHeaders().getContentType() == null) {
                    this.mRequest.getHeaders().setContentType(this.mWriter.getContentType());
                }
                if (this.mWriter.length() >= 0) {
                    this.mRequest.getHeaders().setContentLength(this.mWriter.length());
                    this.mSink = this.mSocket;
                } else {
                    this.mRequest.getHeaders().getHeaders().set("Transfer-Encoding", "Chunked");
                    this.mSink = new ChunkedOutputFilter(this.mSocket);
                }
            } else {
                this.mSink = this.mSocket;
            }
            this.mSocket.setEndCallback(this.mReporter);
            this.mSocket.setClosedCallback(new CompletedCallback() {
                public void onCompleted(Exception ex) {
                }
            });
            String rs = this.mRequest.getRequestString();
            this.mRequest.logv("\n" + rs);
            Util.writeAll((DataSink) exchange, rs.getBytes(), new CompletedCallback() {
                public void onCompleted(Exception ex) {
                    if (AsyncHttpResponseImpl.this.mWriter != null) {
                        AsyncHttpResponseImpl.this.mWriter.write(AsyncHttpResponseImpl.this.mRequest, AsyncHttpResponseImpl.this, new CompletedCallback() {
                            public void onCompleted(Exception ex) {
                                AsyncHttpResponseImpl.this.onRequestCompleted(ex);
                            }
                        });
                    } else {
                        AsyncHttpResponseImpl.this.onRequestCompleted(null);
                    }
                }
            });
            LineEmitter liner = new LineEmitter();
            exchange.setDataCallback(liner);
            liner.setLineCallback(this.mHeaderCallback);
        }
    }

    protected void onRequestCompleted(Exception ex) {
    }

    protected void report(Exception e) {
        super.report(e);
        this.mSocket.setDataCallback(new NullDataCallback() {
            public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
                super.onDataAvailable(emitter, bb);
                AsyncHttpResponseImpl.this.mSocket.close();
            }
        });
        this.mSocket.setWriteableCallback(null);
        this.mSocket.setClosedCallback(null);
        this.mSocket.setEndCallback(null);
        this.mCompleted = true;
    }

    public AsyncHttpResponseImpl(AsyncHttpRequest request) {
        this.mRequest = request;
    }

    public ResponseHeaders getHeaders() {
        return this.mHeaders;
    }

    private void assertContent() {
        if (this.mFirstWrite) {
            this.mFirstWrite = false;
            if (!$assertionsDisabled && this.mRequest.getHeaders().getHeaders().get("Content-Type") == null) {
                throw new AssertionError();
            } else if (!$assertionsDisabled && this.mRequest.getHeaders().getHeaders().get("Transfer-Encoding") == null && this.mRequest.getHeaders().getContentLength() == -1) {
                throw new AssertionError();
            }
        }
    }

    public void write(ByteBuffer bb) {
        assertContent();
        this.mSink.write(bb);
    }

    public void write(ByteBufferList bb) {
        assertContent();
        this.mSink.write(bb);
    }

    public void end() {
        write(ByteBuffer.wrap(new byte[0]));
    }

    public void setWriteableCallback(WritableCallback handler) {
        this.mSink.setWriteableCallback(handler);
    }

    public WritableCallback getWriteableCallback() {
        return this.mSink.getWriteableCallback();
    }

    public boolean isOpen() {
        return this.mSink.isOpen();
    }

    public void setClosedCallback(CompletedCallback handler) {
        this.mSink.setClosedCallback(handler);
    }

    public AsyncServer getServer() {
        return this.mSocket.getServer();
    }

    public String charset() {
        Multimap mm = Multimap.parseHeader(getHeaders().getHeaders(), "Content-Type");
        if (mm != null) {
            String cs = mm.getString("charset");
            if (cs != null && Charset.isSupported(cs)) {
                return cs;
            }
        }
        return null;
    }
}
